package com.katesoft.scale4j.rttp.messaging;

import static com.katesoft.scale4j.common.services.IBeanNameReferences.RTTP_SPRING_HAZELCAST_BRIDGE;

import java.util.concurrent.BlockingQueue;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.katesoft.scale4j.rttp.client.ClusterIsNotActiveException;
import com.katesoft.scale4j.rttp.client.IClusterInstanceAware.ClusterInstanceAwareBean;
import com.katesoft.scale4j.rttp.hibernate.SpringHazelcastBridge;

/**
 * Factory bean which can be used for in-memory distributed queue creation.
 * <p/>
 * created according to http://forum.springframework.org/showthread.php?t=66915
 * 
 * @author kate2007
 */
public class HazelcastQueueFactoryBean extends ClusterInstanceAwareBean implements
         FactoryBean<BlockingQueue<?>>, BeanNameAware, InitializingBean, ApplicationContextAware {
   private String inMemoryQueueName, beanName;
   private ApplicationContext applicationContext;

   /**
    * create distributed in-memory queue using hazelcast cluster reference.
    * 
    * @return in-memory distributed queue.
    */
   @Override
   public BlockingQueue<?> getObject() {
      if (getInstance().getLifecycleService().isRunning()) {
         return getInstance().getQueue(inMemoryQueueName);
      } else {
         throw new ClusterIsNotActiveException(getInstance());
      }
   }

   /**
    * @return BlockingQueue class
    */
   @Override
   public Class<?> getObjectType() {
      return BlockingQueue.class;
   }

   /**
    * @return true
    */
   @Override
   public boolean isSingleton() {
      return true;
   }

   @Override
   public void setBeanName(String beanName) {
      this.beanName = beanName;
   }

   /**
    * set the name of in-memory queue inside hazelcast cluster.
    * 
    * @param inMemoryQueueName
    *           name of hazelcast queue to be used
    */
   public void setInMemoryQueueName(String inMemoryQueueName) {
      this.inMemoryQueueName = inMemoryQueueName;
   }

   @Override
   public void afterPropertiesSet() {
      if (inMemoryQueueName == null) {
         inMemoryQueueName = beanName;
      }
      if (getInstance() == null) {
         setClusterInstance(applicationContext.getBean(RTTP_SPRING_HAZELCAST_BRIDGE,
                  SpringHazelcastBridge.class).getHazelcastInstance());
      }
   }

   @Override
   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
      this.applicationContext = applicationContext;
   }
}
